package prj3;

import java.util.LinkedList;
import java.util.List;

import prj3.exceptions.EmptyListException;

public class BufferedEarthCell extends EarthCell {

	int maxBufferSize;

	List values = new LinkedList();

	public BufferedEarthCell(SphericalGrid grid, SphericalCoordinate coord,
			int maxBufferSize) {
		super(grid, coord);
		this.maxBufferSize = maxBufferSize;
	}

	public BufferedEarthCell(SphericalGrid grid, SphericalCoordinate coord,
			float _value, int maxBufferSize) {
		super(grid, coord, _value);
		this.maxBufferSize = maxBufferSize;
	}

	private synchronized boolean pushValue(float value) {
		if (values.size() < maxBufferSize) {
			values.add(new Float(value));
			minPos = maxPos = -1;
			return true;
		}
		return false;
	}

	private synchronized float popValue() throws EmptyListException {
		if (values.size() > 0) {
			float value = ((Float) values.remove(0)).floatValue();
			minPos = maxPos = -1;
			return value;
		}
		throw new EmptyListException();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see prj3.prj2.ICell#getValue()
	 */
	public float getValue() {
		return value;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see prj3.prj2.ICell#setValue(float)
	 */
	public void setValue(float value) {
		// if(mutable)
		this.value = value;
		// else
		// throw new AssertionError(!mutable);
		minPos = maxPos = -1;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see prj3.prj2.IHistoryValue#switchValues()
	 */
	public synchronized boolean switchValues() {
		if (pushValue(value)) {
			float t = oldValue;
			oldValue = value;
			value = t;
			return true;
		}
		return false;
	}

	public synchronized float takeValue() throws EmptyListException {
		return popValue();
	}

	/**
	 * Returns the minimum value of all values stored for this cell
	 * 
	 * @return
	 * @throws EmptyListException
	 */
	public synchronized float getMinimumValue(int minTimePos, int maxTimePos)
			throws EmptyListException {
		java.util.Iterator it = values.iterator();
		int counter = 0;
		while (it.hasNext()) {
			Float value = (Float) it.next();
			if (counter < minTimePos) {
				counter++;
				continue;
			}
			if (counter > maxTimePos)
				break;
			if (counter == minTimePos) {
				minPos = minTimePos;
				minValue = value.floatValue();
			} else if (value.floatValue() < minValue) {
				minPos = counter;
				minValue = value.floatValue();
			}
			counter++;
		}
		return minValue;

	}

	public synchronized float getAverageValue(int minTimePos, int maxTimePos)
			throws EmptyListException {
		java.util.Iterator it = values.iterator();
		int counter = 0;
		float avgValue = 0;
		int numInCalc = 0;
		while (it.hasNext()) {
			Float value = (Float) it.next();
			if (counter < minTimePos) {
				counter++;
				continue;
			}
			if (counter > maxTimePos)
				break;
			avgValue += value.floatValue();
			numInCalc++;
			counter++;
		}
		return avgValue / (float) numInCalc;

	}

	/**
	 * Returns the position of the minimum value (0 means old)
	 * 
	 * @return
	 * @throws EmptyListException
	 */
	public synchronized int getMinimumPosition(int minTimePos, int maxTimePos)
			throws EmptyListException {
		if (minPos == -1)
			getMinimumValue(minTimePos, maxTimePos);
		return minPos;
	}

	/**
	 * Returns the maximum value of all values stored for this cell
	 * 
	 * @return
	 * @throws EmptyListException
	 */
	public synchronized float getMaximumValue(int minTimePos, int maxTimePos)
			throws EmptyListException {
		java.util.Iterator it = values.iterator();
		int counter = 0;
		while (it.hasNext()) {
			Float value = (Float) it.next();
			if (counter < minTimePos) {
				counter++;
				continue;
			}
			if (counter > maxTimePos)
				break;
			if (counter == minTimePos) {
				maxPos = counter;
				maxValue = value.floatValue();
			} else if (value.floatValue() > maxValue) {
				maxPos = counter;
				maxValue = value.floatValue();
			}
			counter++;
		}
		return maxValue;

	}

	/**
	 * Returns the position of the maximum value (0 means old)
	 * 
	 * @return
	 * @throws EmptyListException
	 */
	public synchronized int getMaximumPosition(int minTimePos, int maxTimePos)
			throws EmptyListException {
		if (maxPos == -1)
			getMaximumValue(minTimePos, maxTimePos);
		return maxPos;
	}

	public synchronized float getValueForPos(int pos) throws EmptyListException {
		java.util.Iterator it = values.iterator();
		int counter = pos;
		Float value = null;
		while (it.hasNext() && counter >= 0) {
			value = (Float) it.next();
			counter--;
		}
		if (counter >= 0)
			throw new EmptyListException();
		return value.floatValue();
	}

	protected int minPos = -1;

	protected int maxPos = -1;

	protected float minValue;

	protected float maxValue;

}
